/**
 * Copyright 2017 区长
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.github.lizhangqu.coreprogress;

import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.utils.PacMap;

/**
 * Stream read/write progress UI callback
 */
public abstract class ProgressUIListener extends ProgressListener {
    private static final int WHAT_START = 0x01;
    private static final int WHAT_UPDATE = 0x02;
    private static final int WHAT_FINISH = 0x03;
    private static final String CURRENT_BYTES = "numBytes";
    private static final String TOTAL_BYTES = "totalBytes";
    private static final String PERCENT = "percent";
    private static final String SPEED = "speed";
    private EventHandler mHandler;
    private EventRunner mEventRunner;

    public ProgressUIListener() {}

    private void ensureHandler() {
        if (mHandler != null) {
            return;
        }
        synchronized (ProgressUIListener.class) {
            if (mHandler == null) {
                mEventRunner = EventRunner.getMainEventRunner();
                mHandler =
                        new EventHandler(mEventRunner) {
                            @Override
                            public void processEvent(InnerEvent event) {
                                int eventId = event.eventId;
                                switch (eventId) {
                                    case WHAT_START:
                                        PacMap startData = event.getPacMap();
                                        if (startData == null) {
                                            return;
                                        }
                                        onUIProgressStart(startData.getLongValue(TOTAL_BYTES));
                                        break;
                                    case WHAT_UPDATE:
                                        PacMap updateData = event.getPacMap();
                                        if (updateData == null) {
                                            return;
                                        }
                                        long numBytes = updateData.getLongValue(CURRENT_BYTES);
                                        long totalBytes = updateData.getLongValue(TOTAL_BYTES);
                                        float percent = updateData.getFloatValue(PERCENT);
                                        float speed = updateData.getFloatValue(SPEED);
                                        onUIProgressChanged(numBytes, totalBytes, percent, speed);
                                        break;
                                    case WHAT_FINISH:
                                        onUIProgressFinish();
                                        break;
                                    default:
                                        break;
                                }
                            }
                        };
            }
        }
    }

    /**
     * The progress changes. If the values of numBytes, totalBytes, percent, and speed are -1,
     * the total size cannot be obtained.
     *
     * @param numBytes   Read/Write Size
     * @param totalBytes Total Size
     * @param percent    Percentage
     * @param speed      speed bytes/ms
     */
    public final void onProgressChanged(long numBytes, long totalBytes, float percent, float speed) {
        if (EventRunner.current() == EventRunner.getMainEventRunner()) {
            onUIProgressChanged(numBytes, totalBytes, percent, speed);
            return;
        }
        ensureHandler();
        InnerEvent innerEvent = InnerEvent.get(WHAT_UPDATE);
        PacMap data = new PacMap();
        data.putLongValue(CURRENT_BYTES, numBytes);
        data.putLongValue(TOTAL_BYTES, totalBytes);
        data.putFloatValue(PERCENT, percent);
        data.putFloatValue(SPEED, speed);
        innerEvent.setPacMap(data);
        mHandler.sendEvent(innerEvent);
    }

    /**
     * Progress Start
     *
     * @param totalBytes Total Size
     */
    public final void onProgressStart(long totalBytes) {
        if (EventRunner.current() == EventRunner.getMainEventRunner()) {
            onUIProgressStart(totalBytes);
            return;
        }
        ensureHandler();
        InnerEvent message = InnerEvent.get(WHAT_START);
        PacMap data = new PacMap();
        data.putLongValue(TOTAL_BYTES, totalBytes);
        message.setPacMap(data);
        mHandler.sendEvent(message);
    }

    /**
     * Progress End
     */
    public final void onProgressFinish() {
        if (EventRunner.current() == EventRunner.getMainEventRunner()) {
            onUIProgressFinish();
            return;
        }
        ensureHandler();
        InnerEvent message = InnerEvent.get(WHAT_FINISH);
        mHandler.sendEvent(message);
    }

    /**
     * The progress changes. If the values of numBytes, totalBytes, percent, and speed are -1,
     * the total size cannot be obtained.
     *
     * @param numBytes   Read/Write Size
     * @param totalBytes Total Size
     * @param percent    Percentage
     * @param speed      Speed bytes/ms
     */
    public abstract void onUIProgressChanged(long numBytes, long totalBytes, float percent, float speed);

    /**
     * Progress Start
     *
     * @param totalBytes Total Size
     */
    public void onUIProgressStart(long totalBytes) {}

    /**
     * Progress End
     */
    public void onUIProgressFinish() {}
}
